package com.jrtc.base.util.payUtil;

import com.jrtc.base.util.wechat.WXPayRequest;
import com.jrtc.base.util.wechat.WXPayUtil;
import com.jrtc.base.util.wechat.config.WXConfig;
import com.jrtc.base.util.wechat.config.WXPayConstants;
import com.jrtc.base.util.wechat.config.WXRequestConfig;

import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.Writer;
import java.math.BigDecimal;
import java.util.HashMap;
import java.util.Map;
import java.util.UUID;

public class WechatPayUtil {

    /**
     * 获取微信支付参数(APP)
     * attach 自定义参数
     * money 实际支付金额
     * orderNumber 订单号
     * notifyUrl 回调地址 "http://39.106.54.2:8080/WXPay/orderResult"
     */
    public static Map<String, String> getWechatAppPayParam(String attach, BigDecimal money,
                                                           String orderNumber, String notifyUrl) throws Exception {
        //获取请求参数
        Map<String,String> map = WXConfig.toMapAPP();
        //传入自己生产的订单号
        map.put("out_trade_no", orderNumber);//订单号
        //金额
        //map.put("total_fee", totalFee(new BigDecimal(0.01)));
        map.put("total_fee", totalFee(money));
        //自定义请求参数
        map.put("attach", attach);
        //回调地址
        map.put("notify_url", map.get("notify_url") + notifyUrl);
        //第一次签名
        String mapStr = WXPayUtil.generateSignedXml(map, WXConfig.KEY);
        //发送统一下单请求 获取到预支付信息
        String result = getCodeUrl(mapStr);
        System.out.println("result:\r" + result);

        //预支付订单信息
        Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
        System.out.println("resultMap:\r" + resultMap);

        //初始化二次签名信息 用第一次请求拿到的信息中的
        Map<String, String> twoMap = new HashMap<String, String>();
        twoMap.put("appid", resultMap.get("appid"));
        twoMap.put("partnerid", resultMap.get("mch_id"));
        twoMap.put("prepayid", resultMap.get("prepay_id"));//第一次发送请求拿到的预支付id
        twoMap.put("noncestr", resultMap.get("nonce_str"));
        twoMap.put("timestamp", WXPayUtil.getCurrentTimestamp() + "");//时间戳
        twoMap.put("package", "Sign=WXPay");
        System.out.println("twoMap:\r" + twoMap);

        //第二次签名 把这个签名给安卓拉起支付请求
        String twoMapStr = WXPayUtil.generateSignedXml(twoMap, WXConfig.KEY);
        System.out.println("twoMapStr:\r" + twoMapStr);

        //给前端调用的Map
        return WXPayUtil.xmlToMap(twoMapStr);

    }

    /**
     * 获取微信支付参数(JSAPI)
     * attach 自定义参数
     * money 实际支付金额
     * orderNumber 订单号
     * notifyUrl 回调地址 "http://39.106.54.2:8080/WXPay/orderResult"
     */
    public static Map<String, String> getWechatJSAPIPayParam(String attach, BigDecimal money,
                                                             String orderNumber, String notifyUrl,String platform) throws Exception {
        //获取请求参数
        Map<String,String> map;
        if(platform.equals("public")){
            map=WXConfig.toMapJSAPI();
        }else{
            map=WXConfig.toMapJSAPIApplet();
        }

        //公众号支付需要用户在公众号或者小程序下的openId
        map.put("openid", attach);
        //传入自己生产的订单号
        map.put("out_trade_no", orderNumber);//订单号
        //金额
        //map.put("total_fee", totalFee(new BigDecimal(0.01)));
        map.put("total_fee", totalFee(money));
        //自定义请求参数
        map.put("attach", attach);
        //回调地址
        map.put("notify_url", map.get("notify_url") + notifyUrl);
        //第一次签名
        String mapStr = WXPayUtil.generateSignedXml(map, WXConfig.KEY);
        //发送统一下单请求 获取到预支付信息
        String result = getCodeUrl(mapStr);
        System.out.println("result:\r" + result);

        //预支付订单信息
        Map<String, String> resultMap = WXPayUtil.xmlToMap(result);
        System.out.println("resultMap:\r" + resultMap);

        //初始化二次签名信息 用第一次请求拿到的信息中的
        Map<String, String> towMap = new HashMap<String, String>();
        String prepayId = resultMap.get("prepay_id");
        towMap.put("appId", map.get("appid"));
        towMap.put("timeStamp", String.valueOf((System.currentTimeMillis() / 1000)));
        towMap.put("nonceStr", WXPayUtil.generateNonceStr());
        towMap.put("package", "prepay_id=" + prepayId);
        towMap.put("signType", WXPayConstants.SignType.MD5.toString());
        System.out.println("towMap:\r" + towMap);

        //第二次签名 把这个签名给公众号h5或者小程序拉起支付请求
        String sign = WXPayUtil.generateSignature(towMap, WXConfig.KEY, WXPayConstants.SignType.MD5);
        towMap.put("paySign", sign);
        towMap.put("sign", sign);

        return towMap;
    }


    //转换金额 有 1.00 转为 100分
    private static String totalFee(BigDecimal price) {
        BigDecimal setScale = price.setScale(2, BigDecimal.ROUND_HALF_DOWN);
        System.out.println(setScale);
        String str = setScale.multiply(new BigDecimal("100")).toString();
        BigDecimal b = new BigDecimal(str.substring(0, str.length() - 3));
        return b.toString();
    }

    //请求统一下单
    private static String getCodeUrl(String mapStr) throws Exception {
        WXRequestConfig wxPayConfig = new WXRequestConfig();
        WXPayRequest wxPayRequest = new WXPayRequest(wxPayConfig);
        UUID uuid = UUID.randomUUID();
        String uuidStr = uuid.toString();
        String resultXml = wxPayRequest.requestWithoutCert(WXConfig.PLACE_AN_ORDERAPI, uuidStr, mapStr, false);
        return resultXml;
    }

    //将InputStream转换为Map
    public static Map<String, String> inStreamToMap(InputStream inStream) throws Exception {
        int _buffer_size = 1024;
        Map<String, String> resultMap = new HashMap<String, String>();
        if (inStream != null) {
            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            byte[] tempBytes = new byte[_buffer_size];
            int count = -1;
            while ((count = inStream.read(tempBytes, 0, _buffer_size)) != -1) {
                outStream.write(tempBytes, 0, count);
            }
            tempBytes = null;
            outStream.flush();
            //将流转换成字符串
            String result = new String(outStream.toByteArray(), "UTF-8");
            //将字符串解析成MAP
            resultMap = WXPayUtil.xmlToMap(result);

        }
        return resultMap;
    }

    //验证支付是否成过
    public static boolean isPaySuccessful(Map<String, String> resultMap) {
        //处理业务逻辑
        String return_code = resultMap.get("return_code");//状态
        String result_code = resultMap.get("result_code");//交易结果
        String out_trade_no = resultMap.get("out_trade_no");//商户订单号(自己生产的订单号)

        //验证签名
        if (WXPayUtil.isSignatureValid(resultMap, WXConfig.KEY)) {
            if (return_code.equals("SUCCESS") && result_code.equals("SUCCESS")) {//交易成功
                if (out_trade_no != null) {//商户订单号
                    return true;
                }
            }
        }

        return false;
    }

    //返回微信支付成功
    public static void paySuccessful(HttpServletResponse response) throws IOException {
        Writer writer = response.getWriter();
        writer.write("<xml><return_code><![CDATA[SUCCESS]]></return_code><return_msg><![CDATA[OK]]></return_msg></xml>");
        writer.flush();
        writer.close();
    }

}
